
package com.borqs.music.util;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ThumbnailUtils;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;

public class AsyncImageLoader {
    private static final String SDCARD_PATH = Environment.getExternalStorageDirectory().getPath();
    private static final String CACHE_ICON_DIR = new File(SDCARD_PATH, "borqs/borqsmusic/icon").getPath(); 
    private static final String IMG_FILE_SUFFIX = ".bmi";
    private static final MyLogger logger = MyLogger.getLogger("AsyncImageLoader");
    private ThreadPoolExecutor mExecutor = new ThreadPoolExecutor(2, 50, 180,
            TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

    private HashMap<String, SoftReference<Bitmap>> mImageCache = new HashMap<String, SoftReference<Bitmap>>();
    private int mWidth;
    private int mHeight;

    public AsyncImageLoader(int width, int height) {
        this.mWidth = width;
        this.mHeight = height;
        File file = new File(CACHE_ICON_DIR);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    public Bitmap loadBitmap(final String imageUrl, final ImageCallback imageCallback) {
        return loadBitmap(imageUrl, imageCallback, false);
    }
    
    public Bitmap loadBitmap(final String imageUrl, final ImageCallback imageCallback,
            final boolean callBackWhenNull) {
        if (mImageCache.containsKey(imageUrl)) {
            SoftReference<Bitmap> softReference = mImageCache.get(imageUrl);
            Bitmap Bitmap = softReference.get();
            if (Bitmap != null) {
                return Bitmap;
            }
        }

        final Handler handler = new Handler() {
            public void handleMessage(Message message) {
                imageCallback.imageLoaded((Bitmap) message.obj, imageUrl);
            }
        };

        mExecutor.execute(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = loadImageFromUrl(imageUrl);
                if (bitmap != null) {
                    // resize the icon with same size of default icon
                    bitmap = ThumbnailUtils.extractThumbnail(bitmap, mWidth, mHeight);
                    mImageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));
                    Message message = handler.obtainMessage(0, bitmap);
                    handler.sendMessage(message);
                } else {
                    if (callBackWhenNull) {
                        Message message = handler.obtainMessage(0, null);
                        handler.sendMessage(message);
                    }
                }
            }
        });

        return null;
    }

    private static Bitmap loadImageFromUrl(String imageUrl) {
        if (imageUrl == null || imageUrl.length() == 0) {
            return null;
        }

        String fileName = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
        int suffixIndex = fileName.lastIndexOf(".");
        if(suffixIndex > 0){
            fileName = fileName.substring(0, suffixIndex);
        }

        try {
            fileName = URLDecoder.decode(fileName, "utf-8");
        } catch (UnsupportedEncodingException e) {
            logger.e(e.getMessage());
        }
        final File file = new File(CACHE_ICON_DIR, fileName + IMG_FILE_SUFFIX);
        
        Bitmap bitmap = null;
        if (file.exists()) {
            bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
        } else {
            InputStream stream = null;
            FileOutputStream out = null;
            try {
                URL url = new URL(imageUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.connect();
                stream = conn.getInputStream();
                bitmap = BitmapFactory.decodeStream(stream);
                if(null == bitmap){
                    return null;
                }
                // save the resized icon in sdcard for cache
                out = new FileOutputStream(file);
                if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) {
                    out.flush();
                }
            } catch (IOException e) {
                logger.e(e.getMessage());
            } finally {
                closeForcibly(out);
                closeForcibly(stream);
            }
        }

        return bitmap;
    }

    private static void closeForcibly(Closeable stream) {
        if (stream == null) {
            return;
        }
        try {
            stream.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static Bitmap loadBitmapFromLocal(String artistName, int width, int height) {
        final File file = new File(CACHE_ICON_DIR, artistName + IMG_FILE_SUFFIX);

        Bitmap bitmap = null;
        if (file.exists()) {
            bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
            // resize the icon with same size of default icon
            bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height);
        }
        return bitmap;
    }
    
    public static interface ImageCallback {
        public void imageLoaded(Bitmap imageBitmap, String imageUrl);
    }
}
